package com.seeyon.apps.nygj.manager.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.addressbook.manager.AddressBookCustomerFieldInfoManager;
import com.seeyon.apps.cip.manager.RegisterManager;
import com.seeyon.apps.cip.manager.ThirdPendingManager;
import com.seeyon.apps.cip.po.RegisterPO;
import com.seeyon.apps.cip.po.ThirdPendingPO;
import com.seeyon.apps.nygj.manager.CustomThirdPendingManager;
import com.seeyon.apps.nygj.util.HttpKit;
import com.seeyon.apps.nygj.util.StrKit;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.formula.FormulaUtil;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.util.DBAgent;
import org.apache.commons.logging.Log;
import org.springframework.util.DigestUtils;
import cn.hutool.core.codec.Base64;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class CustomThirdPendingManagerImpl implements CustomThirdPendingManager {

    private static final Log log = CtpLogFactory.getLog(CustomThirdPendingManagerImpl.class);
    private RegisterManager registerManager = (RegisterManager) AppContext.getBean("registerManager");
    private ThirdPendingManager thirdPendingManager = (ThirdPendingManager) AppContext.getBean("thirdPendingManager");
    private AddressBookCustomerFieldInfoManager addressBookCustomerFieldInfoManager = (AddressBookCustomerFieldInfoManager) AppContext.getBean("addressBookCustomerFieldInfoManager");


    /**
     * 保存第三方待办事项
     * <p>
     * 本方法用于从第三方系统（如dwp系统）获取当前用户的待办事项，并保存到本地数据库中
     * 它首先获取当前用户信息，然后通过HTTP请求与第三方系统交互，获取待办事项数据，
     * 并将这些数据转换为本地对象进行保存
     *
     * @throws BusinessException 当获取待办事项数据或保存过程中发生错误时抛出
     */
    @Override
    public void saveThirdPending() throws BusinessException {
        try {
            // 获取当前用户信息
            User user = AppContext.getCurrentUser();
            String loginName = user.getLoginName();
            log.info("获取当前用户信息:" + loginName);
            // 从配置中获取第三方系统的URL
            String dwp_token_url = StrKit.str(FormulaUtil.getVar("dwp_token_url"));
            String dwp_pending_url = StrKit.str(FormulaUtil.getVar("dwp_pending_url"));
            String dwp_sso_url = StrKit.str(FormulaUtil.getVar("dwp_sso_url"));
            String appCode = StrKit.str(FormulaUtil.getVar("appCode"));

            // 根据应用编码获取注册信息
            RegisterPO registerPO = registerManager.getRegisterIdByCode(appCode);
            if (registerPO == null) {
                log.info("应用注册中应用编码有误:" + appCode);
            } else {
                // 准备请求第三方系统token的参数
                Map<String, Object> tokenMap = new HashMap<>();
                tokenMap.put("username", loginName);

                // 发起HTTP请求获取token
                String token_result = HttpKit.post(dwp_token_url, new HashMap<String, Object>(), JSON.toJSONString(tokenMap));
                log.info("dwp系统获取token接口返回信息:" + token_result);

                // 解析token响应数据
                JSONObject token_obj = JSONObject.parseObject(token_result);
                String token_code = StrKit.str(token_obj.get("code"));

                // 如果获取token成功
                if ("0".equals(token_code)) {
                    String token = StrKit.str(token_obj.get("data"));
                    int size = 200;

                    List<ThirdPendingPO> pendingList = new ArrayList<ThirdPendingPO>();
                    // 分页获取待办事项
                    for (int i = 1; i <= 100; i++) {
                        String pending_url = dwp_pending_url + "?belongType=-1&current=" + i + "&size=" + size + "&descs=create_time";
                        log.info("查询dwp系统待办url地址:" + pending_url);

                        // 设置请求头
                        Map<String, Object> headerMap = new HashMap<String, Object>();
                        headerMap.put("Authorization", "Bearer " + token);

                        // 发起HTTP请求获取待办事项
                        String pending_result = HttpKit.get(pending_url, headerMap);
                        JSONObject pending_obj = JSONObject.parseObject(pending_result);
                        String pending_code = StrKit.str(pending_obj.get("code"));

                        // 如果获取待办事项成功
                        if ("0".equals(pending_code)) {
                            JSONObject data_obj = pending_obj.getJSONObject("data");
                            String num = StrKit.str(data_obj.get("total"));
                            log.info("获取dwp系统待办数据成功总条数:" + num);

                            // 处理待办事项数据
                            JSONArray records = data_obj.getJSONArray("records");
                            if (records.isEmpty()) {
                                break;
                            } else {
                                for (int j = 0; j < records.size(); j++) {
                                    JSONObject record_obj = records.getJSONObject(j);
                                    String id = StrKit.str(record_obj.get("id"));
                                    String flowName = StrKit.str(record_obj.get("flowName"));
                                    String startTime = StrKit.str(record_obj.get("startTime"));
                                    String initiatorName = StrKit.str(record_obj.get("initiatorName"));

                                    ThirdPendingPO thirdPendingPO = new ThirdPendingPO();
                                    thirdPendingPO.setIdIfNew();
                                    thirdPendingPO.setRegisterId(registerPO.getId());
                                    thirdPendingPO.setTitle(flowName);
                                    thirdPendingPO.setTaskId(id);
                                    thirdPendingPO.setSenderName(initiatorName);
                                    if (!"".equals(startTime)) {
                                        Date startDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startTime);
                                        thirdPendingPO.setCreationDate(startDate);
                                    }
                                    String ssoUrl = dwp_sso_url + "?id=" + id + "&token=" + token;
                                    thirdPendingPO.setUrl(ssoUrl);
                                    thirdPendingPO.setClassify("DWP");
                                    thirdPendingPO.setState(0);
                                    thirdPendingPO.setReceiverId(user.getId());
                                    pendingList.add(thirdPendingPO);
                                }
                            }
                        } else {
                            String pending_msg = StrKit.str(pending_obj.get("msg"));
                            log.error("获取dwp系统待办数据失败:" + pending_msg);
                        }
                    }
                    //删除当前登录人员历史待办信息
                    deleteThirdPending(user.getId());
                    // 保存待办事项数据
                    if (!pendingList.isEmpty()) {
                        thirdPendingManager.savePendings(pendingList);
                    } else {
                        log.info("待办事项数据为空");
                    }
                } else {
                    String token_msg = StrKit.str(token_obj.get("msg"));
                    log.error("获取token失败:" + token_msg);
                }
            }
        } catch (Exception e) {
            log.error("获取dwp系统待办数据异常信息:", e);
        }
    }

    /**
     * 保存集成第三方待办事项
     * 该方法从第三方系统获取当前用户的待办事项，并保存到本地数据库
     * 主要步骤包括：
     * 1. 获取当前用户信息
     * 2. 根据应用编码获取注册信息
     * 3. 构建请求参数和header，调用第三方系统接口获取待办事项
     * 4. 解析响应数据，转换为本地对象并保存
     * 5. 删除历史待办事项
     */
    public void saveIntegrationThirdPending() throws BusinessException {
        try {
            // 获取当前用户信息
            User user = AppContext.getCurrentUser();
            String loginName = user.getLoginName();
            log.info("获取当前用户信息:" + loginName);
            String integrationCode = StrKit.str(FormulaUtil.getVar("IntegrationCode"));
            // 根据应用编码获取注册信息
            RegisterPO registerPO = registerManager.getRegisterIdByCode(integrationCode);
            if (registerPO == null) {
                log.info("应用注册中应用编码有误:" + integrationCode);
            } else {

                /*主数据编码*/
                String zsjCode = addressBookCustomerFieldInfoManager.getByMemberId(user.getId()).getExtAttr4();
                log.info("主数据编码:" + zsjCode);
                if (!"".equals(zsjCode)) {
                    String keySecret = StrKit.str(FormulaUtil.getVar("keySecret"));
                    log.info("keySecret:" + keySecret);
                    String appID = StrKit.str(FormulaUtil.getVar("appID"));
                    log.info("appID:" + appID);
                    String platformAppID = StrKit.str(FormulaUtil.getVar("platformAppID"));
                    log.info("platformAppID:" + platformAppID);
                    String platformSecret = StrKit.str(FormulaUtil.getVar("platformSecret"));
                    log.info("platformSecret:" + platformSecret);
                    String taskUrl = StrKit.str(FormulaUtil.getVar("yth_url")) + "/OSPPortal/CSCPortal.jsp";
                    log.info("taskUrl:" + taskUrl);
                    String startTs = String.valueOf(System.currentTimeMillis());

                    String tokenStr = keySecret + "appID" + appID + "timestamp" + startTs + "user" + user + keySecret;
                    log.info("tokenStr:" + tokenStr);
                    String token = DigestUtils.md5DigestAsHex(tokenStr.getBytes(StandardCharsets.UTF_8)).toUpperCase();
                    log.info("appID:" + appID);
                    String base64Str = Base64.encode(platformAppID + ":" + platformSecret);
                    Map<String, Object> headerMap = new HashMap<String, Object>();
                    headerMap.put("Accept", "application/json;charset=utf-8");
                    headerMap.put("Content-Type", "application/json;charset=utf-8");
                    headerMap.put("appID", platformAppID);
                    headerMap.put("Authorization", "Basic " + base64Str);
                    headerMap.put("appIDnew", appID);
                    headerMap.put("auth-token", token);
                    log.info("headerMap:" + JSON.toJSONString(headerMap));
                    Map<String, Object> bodyMap = new HashMap<String, Object>();
                    bodyMap.put("UserName", zsjCode);
                    bodyMap.put("TASK_PAGING_LOAD", "1");
                    bodyMap.put("PAGING_START", "0");
                    bodyMap.put("PAGING_SHOWNUM", "100");
                    String dataJson = JSON.toJSONString(bodyMap);
                    log.info("dataJson:" + dataJson);
                    String pendingUrl = StrKit.str(FormulaUtil.getVar("taskUrl"))+"/cwywyapi/0010110021/v2.1/Sub/NanY/OA/cscec/load/pendingTask";
                    log.info("pendingUrl:" + pendingUrl);
                    String result = HttpKit.post(pendingUrl, headerMap, dataJson);
                    log.info("获取财务一体化待办返回信息:" + result);
                    JSONObject jsonObject = JSONObject.parseObject(result);
                    String code = str(jsonObject.get("code"));
                    if ("00000".equals(code)) {
                        JSONObject dataObj = jsonObject.getJSONObject("data");
                        String data_code = str(dataObj.get("code"));
                        if ("0".equals(data_code)) {
                            if (!dataObj.containsKey("TaskList")) {
                                //删除当前登录人员历史待办信息
                                deleteIntegrationThirdPending(user.getId());
                            } else {
                                JSONArray dataArray = dataObj.getJSONArray("TaskList");
                                List<ThirdPendingPO> pendingList = new ArrayList<ThirdPendingPO>();
                                for (int i = 0; i < dataArray.size(); i++) {
                                    JSONObject taskObj = dataArray.getJSONObject(i);
                                    ThirdPendingPO thirdPendingPO = new ThirdPendingPO();
                                    thirdPendingPO.setIdIfNew();
                                    thirdPendingPO.setRegisterId(registerPO.getId());
                                    thirdPendingPO.setTitle(StrKit.str(taskObj.get("EXT_STR02")));
                                    thirdPendingPO.setTaskId(StrKit.str(taskObj.get("OP_ID")));
                                    thirdPendingPO.setSenderName(StrKit.str(taskObj.get("OP_USER_NAME")));
                                    String EXT_DAT01 = StrKit.str(taskObj.get("EXT_DAT01"));
                                    if (!"".equals(EXT_DAT01)) {
                                        long secondTimestamp = Long.parseLong(EXT_DAT01) / 1000;
                                        Date date = new Date(secondTimestamp * 1000);
                                        thirdPendingPO.setCreationDate(date);
                                    }
                                    StringBuilder stb = new StringBuilder();
                                    stb.append(taskUrl).append("?openType=loadPendingBill&djbh=");
                                    stb.append(str(taskObj.get("BIZ_DJBH"))).append("&flowid=").append(str(taskObj.get("FLOW_ID")));
                                    stb.append("&nodeid=").append(str(taskObj.get("NODE_TAG")));
                                    stb.append("&opid=").append(str(taskObj.get("OP_ID")));
                                    String timestamp = String.valueOf(System.currentTimeMillis());

                                    String tokenStr_new = keySecret + "appID" + appID + "timestamp" + timestamp + "user" + zsjCode + keySecret;
                                    String token_new = DigestUtils.md5DigestAsHex(tokenStr_new.getBytes(StandardCharsets.UTF_8)).toUpperCase();
                                    stb.append("&token=").append(token_new).append("&user=").append(zsjCode);
                                    stb.append("&appID=").append(appID).append("&timestamp=").append(timestamp);
                                    thirdPendingPO.setUrl(stb.toString());
                                    thirdPendingPO.setClassify("TIP-Todo");
                                    thirdPendingPO.setState(0);
                                    thirdPendingPO.setReceiverId(user.getId());
                                    pendingList.add(thirdPendingPO);
                                }
                                //删除当前登录人员历史待办信息
                                deleteIntegrationThirdPending(user.getId());
                                // 保存待办事项数据
                                if (!pendingList.isEmpty()) {
                                    thirdPendingManager.savePendings(pendingList);
                                } else {
                                    log.info("待办事项数据为空");
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取财务一体化系统待办数据异常信息:", e);
        }
    }

    /**
     * 判断是否是DWP系统
     * 通过参数中的singleBoardId来判断对应的注册信息是否属于DWP系统
     *
     * @param param 包含singleBoardId的参数映射
     * @return 如果是DWP系统则返回true，否则返回false
     * @throws BusinessException 当操作业务逻辑错误时抛出
     */
    @Override
    public boolean isDwpSystem(Map<String, String> param) throws BusinessException {
        // 默认认为是DWP系统
        boolean isDwpSystem = true;
        try {
            // 获取并处理singleBoardId参数
            String singleBoardId = StrKit.str(param.get("singleBoardId"));
            log.info("待处理第三方记录的注册信息ID:" + singleBoardId);
            if (singleBoardId.contains("_")) {
                singleBoardId = singleBoardId.split("_")[1];
            }
            log.info("待处理第三方记录的新注册信息ID:" + singleBoardId);
            // 根据处理后的singleBoardId获取注册信息
            RegisterManager registerManager = (RegisterManager) AppContext.getBean("registerManager");
            RegisterPO registerPO = registerManager.getRegisterById(Long.parseLong(singleBoardId));
            String app_code = "";
            // 获取当前应用代码和注册信息中的应用代码
            String appCode = StrKit.str(FormulaUtil.getVar("appCode"));
            if (registerPO != null) {
                log.info("待处理第三方记录的注册信息:" + registerPO);
                app_code = StrKit.str(registerPO.getAppCode());
            }

            // 比较应用代码，不一致则不是DWP系统
            if (!app_code.equals(appCode)) {
                isDwpSystem = false;
            }
        } catch (Exception e) {
            // 异常处理，记录日志
            log.error("dwp自定义栏目拉取数据报错异常信息:", e);
            isDwpSystem = false;
        }
        // 返回判断结果
        return isDwpSystem;
    }

    /**
 * 判断是否是一体化系统
 * 通过给定的参数判断当前请求是否来自一体化系统
 * 主要通过解析参数中的singleBoardId，获取注册信息，并与当前应用代码进行比较来判断
 *
 * @param param 包含判断所需信息的参数映射，主要是singleBoardId
 * @return 如果是一体化系统，则返回true；否则返回false
 * @throws BusinessException 如果发生业务异常
 */
public boolean isIntegrationSystem(Map<String, String> param) throws BusinessException {
    // 默认认为是一体化系统
    boolean isIntegrationSystem = true;
    try {
        // 获取并处理singleBoardId
        String singleBoardId = StrKit.str(param.get("singleBoardId"));
        log.info("一体化第三方记录的注册信息ID:" + singleBoardId);
        if (singleBoardId.contains("_")) {
            singleBoardId = singleBoardId.split("_")[1];
        }
        log.info("一体化第三方记录的新注册信息ID:" + singleBoardId);
        // 根据处理后的singleBoardId获取注册信息
        RegisterManager registerManager = (RegisterManager) AppContext.getBean("registerManager");
        RegisterPO registerPO = registerManager.getRegisterById(Long.parseLong(singleBoardId));
        String app_code = "";
        // 获取当前应用代码和注册信息中的应用代码
        String appCode = StrKit.str(FormulaUtil.getVar("IntegrationCode"));
        if (registerPO != null) {
            log.info("一体化第三方记录的注册信息:" + registerPO);
            app_code = StrKit.str(registerPO.getAppCode());
        }

        // 比较应用代码，不一致则不是DWP系统
        if (!app_code.equals(appCode)) {
            isIntegrationSystem = false;
        }
    } catch (Exception e) {
        // 异常处理，记录日志
        log.error("一体化自定义栏目拉取数据报错异常信息:", e);
        isIntegrationSystem = false;
    }
    // 返回判断结果
    return isIntegrationSystem;
}


    /**
     * 删除指定收件人的所有待处理的第三方记录
     * 此方法通过更新数据库来删除状态为待处理（state = 0）的记录
     *
     * @param receiverId 收件人的唯一标识符，用于确定要删除的记录
     * @throws BusinessException 当数据库更新操作失败时抛出此异常
     */
    private void deleteThirdPending(Long receiverId) throws BusinessException {
        // 构造HQL查询语句，用于删除状态为0（即待处理）的记录
        String hql = "delete " + ThirdPendingPO.class.getName() + " where classify = 'DWP' and state = 0 and receiverId = :receiverId";

        // 创建参数映射，用于绑定查询语句中的参数
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("receiverId", receiverId);

        // 执行数据库批量更新操作，删除符合条件的记录
        DBAgent.bulkUpdate(hql, params);
    }

    /**
     * 删除特定接收者的第三方待处理消息
     *
     * 此方法通过指定的HQL查询来删除数据库中符合特定条件的第三方待处理消息
     * 它专注于删除分类为'TIP-Todo'、状态为0且接收者ID匹配的消息
     *
     * @param receiverId 接收者的ID，用于标识待处理消息的接收者
     * @throws BusinessException 当数据库更新操作失败时抛出的异常
     */
    private void deleteIntegrationThirdPending(Long receiverId) throws BusinessException {
        // 构建HQL查询字符串，旨在删除符合特定条件的记录
        String hql = "delete " + ThirdPendingPO.class.getName() + " where classify = 'TIP-Todo' and state = 0 and receiverId = :receiverId";

        // 创建参数映射，用于在HQL查询中绑定接收者ID
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("receiverId", receiverId);

        // 执行HQL查询，进行批量更新（即删除操作）
        DBAgent.bulkUpdate(hql, params);
    }

    private static String str(Object o) {
        // 判断对象是否为null
        if (o == null) {
            return "";
        }
        // 判断对象是否已经是字符串类型
        if (o instanceof String) {
            return (String) o;
        }
        // 对象不是null且不是字符串类型，调用toString方法转换
        return o.toString();
    }
}
